/*****************************************************************************
 * 
 * Copyright [2013] [Mervin.Wong]
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 *       
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *  
 *****************************************************************************/
package base.feature;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import util.D;

import base.Network;

/**
 *@name ClusterCofficient.java
 *@description 
 *@author 王进法<Mervin.Wong>
 *@version 
 *@Date 2013-1-13上午10:46:38
 */
/*********************************************************************************
 *
 *
 *
 **********************************************************************************/

public class ClusterCofficient implements InterfaceClusterCoefficient {
	private Network net = null;
	
	public ClusterCofficient(){
		
	}
	public ClusterCofficient(Network net){
		this.net = net;
	}

	public void set(Network net){
		this.net = net;
	}
	public Network get(){
		return this.net;
	}
	/*********************************************************************************
	 *
	 * 基本函数
	 *
	 **********************************************************************************/
	/**
	 * @name nodeClusterCofficient
	 * @description 节点的聚类系数
	 * @param nodeId
	 * @return float clusterCofficient
	 * @see base.feature.InterfaceClusterCoefficient#nodeClusterCofficient(int)
	 */
	@Override
	public float nodeClusterCofficient (Number nodeId) {
		// TODO Auto-generated method stub
		HashSet<Number> adjNodesId = this.net.getAdjNodesId(nodeId);//nodeId的邻接点
		Number firstNodeId = 0, secondNodeId = 0;
		int i = 1, j, edgeCount =0;
		int nodeCount = adjNodesId.size();
		for (Iterator<Number> iterator = adjNodesId.iterator(); iterator.hasNext();) {
			firstNodeId = (Number) iterator.next();
			j = 1;
			for (Iterator<Number> iterator2 = adjNodesId.iterator(); iterator2.hasNext();) {
				secondNodeId = (Number) iterator2.next();
				if(j > i){
					if(this.net.isHasEdge(firstNodeId, secondNodeId)){
						edgeCount++;
					}
				}
			}
			i++;
		}
		return edgeCount/(float)(nodeCount*(nodeCount-1)/2);
	}
	
	/**
	 * @name nodeClusterCofficient
	 * @description 节点的聚类系数
	 * @param Network net
	 * @param nodeId
	 * @return float clusterCofficient
	 * @see base.feature.InterfaceClusterCoefficient#nodeClusterCofficient(base.Network, int)
	 */
	@Override
	public float nodeClusterCofficient(Network net, Number nodeId) {
		// TODO Auto-generated method stub
		HashSet<Number> adjNodesId = net.getAdjNodesId(nodeId);
		Number firstNodeId = null;
		Number secondNodeId =null;
		int i = 1, j;
		int edgeCount = 0;
		int nodeCount = adjNodesId.size();
		for (Iterator<Number> iterator = adjNodesId.iterator(); iterator.hasNext();) {
			firstNodeId = (Number) iterator.next();
			j = 1;
			for (Iterator<Number> iterator2 = adjNodesId.iterator(); iterator2.hasNext();) {
				secondNodeId = (Number) iterator2.next();
				if(j > i){
					if(net.isHasEdge(firstNodeId, secondNodeId)){
						edgeCount++;
					}
				}
				j++;
			}
			i++;
		}
		return edgeCount/((float)nodeCount*(nodeCount-1)/2);
	}

	/**
	 * @name nodesClusterCofficient
	 * @description 多个节点的聚类系数
	 * @param nodesId
	 * @return HashSet<Number> clusterCofficient
	 * @see base.feature.InterfaceClusterCoefficient#nodesClusterCofficient( HashSet<Number>)
	 */
	@Override
	public HashMap<Number, Number> nodesClusterCofficient(HashSet<Number> nodesId) {
		// TODO Auto-generated method stub
		HashMap<Number, Number> cc = new HashMap<Number, Number>();
		Number nodeId = null;
		for (Iterator<Number> iterator = nodesId.iterator(); iterator.hasNext();) {
			nodeId = (Number) iterator.next();
			cc.put(nodeId, this.nodeClusterCofficient(nodeId));
		}
		return cc;
	}
	
	/**
	 * @name nodesClusterCofficient
	 * @description 多个节点的聚类系数
	 * @param Network net
	 * @param nodesId
	 * @return HashSet<Number> clusterCofficient
	 * @see base.feature.InterfaceClusterCoefficient#nodesClusterCofficient(base.Network, int[])
	 */
	@Override
	public HashMap<Number, Number> nodesClusterCofficient(Network net, HashSet<Number> nodesId) {
		// TODO Auto-generated method stub
		HashMap<Number, Number> cc = new HashMap<Number, Number>();
		Number nodeId = null;
		for (Iterator<Number> iterator = nodesId.iterator(); iterator.hasNext();) {
			nodeId = (Number) iterator.next();
			cc.put(nodeId, this.nodeClusterCofficient(net, nodeId));
		}
		return cc;
	}

	/**
	 * @name netClusterCofficient
	 * @description 网络的聚类系数
	 * @return float clusterCoefficient
	 * @see base.feature.InterfaceClusterCoefficient#netClusterCoefficient()
	 */
	@Override
	public float netClusterCoefficient() {
		// TODO Auto-generated method stub
		Set<Number> nodesId = this.net.topology.keySet();
		int nodeNum = this.net.nodeNum;
		float cc = 0;
		for (Iterator<Number> iterator = nodesId.iterator(); iterator.hasNext();) {
			cc += this.nodeClusterCofficient((Number)iterator.next());
			
		}
		return cc/nodeNum;
	}
	
	/**
	 * @name netClusterCofficient
	 * @description 网络的聚类系数
	 * @param net
	 * @return float clusterCoefficient
	 * @see base.feature.InterfaceClusterCoefficient#netClusterCoefficient(base.Network)
	 */
	@Override
	public float netClusterCoefficient(Network net) {
		// TODO Auto-generated method stub
		Set<Number> nodesId = net.topology.keySet();
		int nodeNum = net.nodeNum;
		float cc = 0;
		for (Iterator<Number> iterator = nodesId.iterator(); iterator.hasNext();) {
			cc += this.nodeClusterCofficient(net, (Number)iterator.next());
		}
		return cc/nodeNum;
	}

}
